import ErrorMessage from "@src/components/ErrorMessage";
import {
  AppRole,
  CreateRoleCommand,
  LoadRoleDetailCommand,
  PagedListOfAppRole,
  Paging,
  QueryRolesCommand,
  RoleManageV1Client,
} from "@src/services/v1_client";
import { useClient } from "@src/utils/useHelper";
import {
  BootstrapIcon,
  BsButton,
  FcForm,
  FcInput,
  formatDate,
  Pagination,
  SolidModal,
  Table,
} from "solid-fire-controls";
import {
  catchError,
  Component,
  createEffect,
  createResource,
  createSignal,
  Index,
  Match,
  Switch,
} from "solid-js";
import { handleError } from "@src/utils/http-utils";
import { Modal } from "bootstrap";
import RoleDetail from "./Detail";
import { withSolidContent } from "sweetalert2-solid-content";
import Swal from "sweetalert2";

const manageClient = useClient(RoleManageV1Client);

const defaultSize = 20;
const defaultResult = new PagedListOfAppRole({ totalCount: 0 });

const RoleList: Component = () => {
  const [paging, setPaging] = createSignal(
    new Paging({ index: 1, size: defaultSize })
  );

  const loadRoles = async (p: Paging) => {
    return await manageClient.queryRoles(new QueryRolesCommand({ paging: p }));
  };

  const [roleList, setRoleList] =
    createSignal<PagedListOfAppRole>(defaultResult);

  const [resource, { mutate, refetch }] = createResource(paging(), loadRoles);
  const refresh = () => {
    catchError(
      () =>
        Promise.resolve(refetch()).then((result) =>
          setRoleList(result ?? defaultResult)
        ),
      handleError
    );
  };

  createEffect(() => {
    catchError(() => setRoleList(resource() ?? defaultResult), handleError);
  });

  const loadRoleDetail = async (roleId?: string) => {
    return await manageClient.loadRoleDetail(
      new LoadRoleDetailCommand({ id: roleId })
    );
  };

  const [editingRole, setEditingRole] = createSignal<AppRole>(new AppRole());
  const [modal, setModal] = createSignal<Modal | undefined>(undefined);

  const viewRoleDetail = (id?: string) => {
    modal()?.show();
    loadRoleDetail(id).then(setEditingRole).catch(handleError);
  };

  const [createModal, setCreateModal] = createSignal<Modal | undefined>(
    undefined
  );
  const [creatingName, setCreatingName] = createSignal("");

  const createRole = () => {
    manageClient
      .createRole(new CreateRoleCommand({ name: creatingName() }))
      .then((result) => {
        if (result.succeeded) {
          withSolidContent(Swal).fire({
            icon: "success",
            title: "创建成功",
          });
          createModal()?.hide();
          refresh();
        } else {
          withSolidContent(Swal).fire({
            icon: "error",
            title: "创建失败",
            html: (
              <Index each={result.errors}>
                {(err, index) => (
                  <p>
                    <strong>[{err().code}]</strong>
                    <span>{err().description}</span>
                  </p>
                )}
              </Index>
            ),
          });
        }
      })
      .catch(handleError);
  };

  const recoveryRole = (id: string) => {
    manageClient
      .recoveryRole(id)
      .then((result) => {
        if (result.succeeded) {
          withSolidContent(Swal).fire({
            icon: "success",
            title: "恢复成功",
          });
        } else {
          withSolidContent(Swal).fire({
            icon: "error",
            title: "恢复失败",
          });
        }
      })
      .then(() => loadRoleDetail(id).then(setEditingRole).catch(handleError))
      .catch(handleError);
  };

  const deleteRole = (id: string) => {
    manageClient
      .deleteRole(id)
      .then((result) => {
        if (result.succeeded) {
          withSolidContent(Swal).fire({
            icon: "success",
            title: "删除成功",
          });
        } else {
          withSolidContent(Swal).fire({
            icon: "error",
            title: "删除失败",
          });
        }
      })
      .then(() => loadRoleDetail(id).then(setEditingRole).catch(handleError))
      .catch(handleError);
  };

  return (
    <div class="d-flex p-2 flex-column h-100" style={{ "max-height": "100%" }}>
      <ErrorMessage
        error={resource.error}
        show={resource.state === "errored"}
      ></ErrorMessage>
      <div class="flex-shrink-1 d-flex grid gap-1 mb-1">
        <BsButton
          variant={"primary"}
          loading={resource.loading}
          onClick={refresh}
          icon={<BootstrapIcon icon="arrow-clockwise"></BootstrapIcon>}
        >
          刷新
        </BsButton>
        <BsButton
          variant="primary"
          onClick={() => {
            setCreatingName("");
            createModal()?.show();
          }}
          icon={<BootstrapIcon icon="plus"></BootstrapIcon>}
        >
          新增
        </BsButton>
      </div>
      <Table
        size="sm"
        loading={resource.loading}
        classList={{
          "flex-grow-1": true,
        }}
        responsive
        fixedHeader
        border={"borderless"}
        hover
        nowrap
        datas={roleList()?.datas}
        columns={[
          { type: "selection" },
          { type: "index" },
          {
            name: "id",
            label: "Id",
            width: 280,
            tooltip: true,
            headerAlign: "start",
          },
          {
            name: "name",
            label: "Name",
            fixed: "left",
            width: 160,
            tooltip: true,
            headerAlign: "center",
          },
          {
            name: "createdTime",
            label: "创建时间",
            children: formatDate(),
          },
          {
            name: "lastModifiedTime",
            label: "最后修改时间",
            children: formatDate(),
          },
          {
            label: "操作",
            fixed: "right",
            width: 100,
            children: (data, index) => (
              <>
                <BsButton
                  size="sm"
                  variant="primary"
                  onClick={() => viewRoleDetail(data.id)}
                  icon={
                    <BootstrapIcon icon="search" class="me-1"></BootstrapIcon>
                  }
                >
                  查看
                </BsButton>
              </>
            ),
          },
        ]}
        slots={{
          header: (ctx) => (
            <Table.Header
              {...ctx}
              classList={{ ...ctx.classList, "table-primary": true }}
            ></Table.Header>
          ),
        }}
      ></Table>
      <div>
        <Pagination
          showTotal
          classList={{ "justify-content-center": true }}
          totalCount={roleList()?.totalCount}
          current={{ page: paging().index!, size: paging().size! }}
          onChanged={(page, size) =>
            setPaging(new Paging({ index: page, size }))
          }
        ></Pagination>
      </div>
      <SolidModal fade onRef={setCreateModal}>
        <SolidModal.Header>
          <SolidModal.Title classList={{ "fs-4": true }}>
            Create Role
          </SolidModal.Title>
          <SolidModal.CloseButton></SolidModal.CloseButton>
        </SolidModal.Header>
        <SolidModal.Body>
          <FcInput
            value={creatingName()}
            onChange={setCreatingName}
            placeholder="Role Name..."
          ></FcInput>
        </SolidModal.Body>
        <SolidModal.Footer>
          <BsButton variant="primary" onClick={() => createRole()}>
            确认
          </BsButton>
        </SolidModal.Footer>
      </SolidModal>
      <SolidModal onRef={setModal} fullscreen>
        <SolidModal.Header>
          <SolidModal.Title>Role: {editingRole().name}</SolidModal.Title>
          <SolidModal.CloseButton></SolidModal.CloseButton>
        </SolidModal.Header>
        <SolidModal.Body>
          <div class="row">
            <div class="col-4">
              <FcForm value={editingRole()} disabled>
                <RoleDetail></RoleDetail>
                <div class="d-flex grid gap-3">
                  <Switch>
                    <Match when={editingRole().deleted}>
                      <BsButton onclick={() => recoveryRole(editingRole().id!)}>
                        恢复
                      </BsButton>
                    </Match>
                    <Match when={!editingRole().deleted}>
                      <BsButton
                        variant="danger"
                        onClick={() => deleteRole(editingRole().id!)}
                      >
                        删除
                      </BsButton>
                    </Match>
                  </Switch>
                </div>
              </FcForm>
            </div>
          </div>
        </SolidModal.Body>
      </SolidModal>
    </div>
  );
};

export default RoleList;
